/**
 * Created by ecervetti on 01/03/14.
 */

/**
 *
 * @param univers {Univers}
 * @constructor
 */
var Duck = function(univers) {
    this.univers =  univers ;
    this.i = 3 ;
    this.j = this.univers.data[this.i].height+1 ;
    this.trajectoire = new Trajectoire(this) ;
    this.decideNewTrajectoire(this.timeTrajectoire,false,false);
};

Duck.prototype = {
    i: null,
    j: null,
    timeTrajectoire : 4000 ,
    /**
     * @type {Univers}
     */
    univers : null ,

    bitchness : 0 , //0->gentil, 1->connard

    /**
     * @type {Trajectoire}
     */
    trajectoire : null ,

    physics : function(timeIntervallSinceLastCalc) {
        var thisDuck = this ;
        //Vol du canard
        var trajectoire = thisDuck.trajectoire ;
        if(!trajectoire.ready)
            return ;
        trajectoire.t   += timeIntervallSinceLastCalc ;
        if( trajectoire.totalTime < trajectoire.t ) {
            thisDuck.i = trajectoire.toI ;
            thisDuck.j = trajectoire.toJ ;
            thisDuck.trajectoire.ready = false ;
            if(thisDuck.bitchness<1) {
                thisDuck.bitchness+=0.025;
            }
            if( thisDuck.univers.selectedCol != thisDuck.i) {
                thisDuck.univers.endJourney();


                return ;
            }
            var timeTrajectoireSouhaite = thisDuck.timeTrajectoire - ( thisDuck.timeTrajectoire*thisDuck.bitchness)*Math.random();

            setTimeout(function(){
                thisDuck.decideNewTrajectoire(timeTrajectoireSouhaite,false,false);
            },1);
        } else {
            var calcul = thisDuck.trajectoire.calc(trajectoire.t) ;
            thisDuck.i      = calcul.x ;
            thisDuck.j      = calcul.y ;
        }
    },



    /**
     *
     * @param wishedTime
     * @param depassementAutorise
     * @param trajPlateAutorisee
     * @returns {*}
     */
    decideNewTrajectoire : function(wishedTime,depassementAutorise,trajPlateAutorisee) {
        var thisDuck = this ;

        thisDuck.trajectoire.originI = thisDuck.i ;
        thisDuck.trajectoire.originJ = thisDuck.j ;
        var calcul ;
        var isCollision ;
        var presenceEchecDepassement = false ;
        var tabPossiblesTrajectoires = [];
        var tabSympathieTrajectoire  = [];
        var t ;
        var i ;
        var timeStep ;
        var minSympathie = 0 ;
        var maxSympathie = -100000 ;
        var meilleurI = 0 ;
        var sympathieCase ;

        var maxAutorise = ( 2+ thisDuck.univers.jPointerIHM + thisDuck.univers.ihm.discrWidth*thisDuck.univers.pente/2 + thisDuck.univers.ihm.discrWidth )  ;

        //console.log("tentative de trajectoire pour "+wishedTime);

        //Je vais trouver le trajet le plus loin possible, que je peux faire dans le temps donné, sans qu'il y ait de collision, ni que je sorte du haut de l'écran
        for(i=thisDuck.univers.lastCreatedX-1;i>thisDuck.i;i--) {

            //console.log("etude de la trajectoire pour " + i);

            thisDuck.trajectoire.toI = i ;
            thisDuck.trajectoire.drawtoI = i ;
            thisDuck.trajectoire.toJ = thisDuck.univers.data[thisDuck.trajectoire.toI].height +1 ;
            //On ne saute pas vers un point plus bas
            if(! trajPlateAutorisee && thisDuck.trajectoire.toJ <= (1+thisDuck.j))
                continue ;
            //plus la somme de la valeur de la case gauche et celle de la case droite sont negatives, plus la case est "sympa" (un creux autour)
            sympathieCase = 2 * thisDuck.trajectoire.toJ  - thisDuck.univers.data[thisDuck.trajectoire.toI - 1].height - thisDuck.univers.data[thisDuck.trajectoire.toI + 1].height  ;
            //Plus le canard est un enfoiré, plus on atténue la sympathie de la case
            //Plus il est gentil, plus on la flatte
            //console.log(sympathieCase);
            sympathieCase = sympathieCase*Math.tan(Math.PI*0.7*(0.5-thisDuck.bitchness)) ;
            //console.log(sympathieCase);

            if(minSympathie > sympathieCase)
                minSympathie = sympathieCase ;
            if(maxSympathie < sympathieCase) {
                maxSympathie = sympathieCase ;
                meilleurI = i ;
            }

            thisDuck.trajectoire.resolve(wishedTime);

            //La trajectoire ne sort pas de l'écran ?

            //console.log("max autorise "+maxAutorise+"max trouve :"+thisDuck.trajectoire.maximum);
            if( ! depassementAutorise && thisDuck.trajectoire.maximum >maxAutorise) {
                //console.log("une trajectoire sort de l'ecran");
                //console.log('la trajectoire sortr de lecran'+thisDuck.trajectoire.maximum);
                presenceEchecDepassement = true ;
                continue ;
            }
            //Pas de collision ?
            isCollision = false ;
            timeStep = wishedTime/(i-thisDuck.i) ;
            for(t=timeStep/2;t<wishedTime;t+=timeStep) {
                calcul = thisDuck.trajectoire.calc(t) ;
                if( calcul.y  < thisDuck.univers.data[ Math.round(calcul.x ) ].height +1 ) {
                    isCollision = true ;
                    break ;
                }
                calcul = thisDuck.trajectoire.calc(t-timeStep/2) ;
                if( calcul.y  < thisDuck.univers.data[ Math.round(calcul.x ) ].height +1 ) {
                    isCollision = true ;
                    break ;
                }
            }

            if(  isCollision) {
                continue ;
            }
            tabPossiblesTrajectoires.push(i) ;
            tabSympathieTrajectoire[tabPossiblesTrajectoires.length-1]=sympathieCase ;
        }

        if( tabPossiblesTrajectoires.length == 0) {

            //2->On a tenté de trouver sans succes un chemin sans collisions en baissant le temps de saut ou 1->le temps initial était trop petit pour une trajectoire sans collision
            if( ! presenceEchecDepassement && ! depassementAutorise) {
                //console.log("Je ne trouve pas de baisse de temps de vol sans collision. J'accepte un dépassement, pour un temps de vol de "+(wishedTime+100));
                return thisDuck.decideNewTrajectoire(wishedTime+100,true,false);
            //1->La demande initiale de temps de saut ne peut pas se faire sans déplacement
            } else if( ! depassementAutorise   ) {
                //console.log("la demande initiale ne peut pas se faire, je baisse le temps de vol demandé "+(wishedTime));
                if(wishedTime<200) {
                    //j'ai diminué sans trouver de collision, j'augmente en acceptant les déplacements
                    return thisDuck.decideNewTrajectoire(wishedTime+100,true,false);
                } else {
                    return thisDuck.decideNewTrajectoire(wishedTime-100,false,false);
                }

            //3->on va prendre le plus petit dépassement n'impliquant pas une collision
            } else {
                if(wishedTime>4000) {
                    //On est remonté, mais sans rien trouvé. C'est qu'il n'y a que des cases plates. On trouve une trajectoire plate, tant pis
                    return thisDuck.decideNewTrajectoire(wishedTime-1000,true,true);
                }
                return thisDuck.decideNewTrajectoire(wishedTime+100,true,false);
            }

        }
        //console.log("Trajectoire trouvée");

        for(i=0;i<tabSympathieTrajectoire.length;i++) {
            tabSympathieTrajectoire[i]+=1-minSympathie;
        }

        if(thisDuck.bitchness<0.1) {
            thisDuck.trajectoire.toI = meilleurI ;
        } else {
            thisDuck.trajectoire.toI = tabPossiblesTrajectoires[  thisDuck.roueDeLaFortune(tabSympathieTrajectoire) ] ;
        }
        thisDuck.trajectoire.toJ = thisDuck.univers.data[thisDuck.trajectoire.toI].height +1 ;
        thisDuck.trajectoire.resolve(wishedTime);
        thisDuck.trajectoire.ready = true ;
    },


    roueDeLaFortune : function(tab) {
        var l = 0 ;
        var i ;
        for(i=0;i<tab.length;i++) {
            l+=tab[i];
        }
        var bing = Math.random()*l;
        l = 0 ;
        for(i=0;i<tab.length;i++) {
            l+=tab[i];
            if(l>=bing) {
                return i ;
            }
        }
        return -1 ;
    }

};


